package com.xuxueli.applyModules.utils.testcharts;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class WordUtils {
    /**
     *将word中某些标签替换成指定的值，并生成一个新的word文档。
     * @param inFilePath word模板文件路径
     * @param outFilePath 填充后输出文件路径
     * @param map  key:word中的占位标签，value对应标签要替换的值。
     * @throws IOException
     */
    public static void insertAndOutFile(String inFilePath, String outFilePath, Map<String,String> map) throws IOException {
        //准备工作，生成docx对象
        String templatePath=inFilePath;
        InputStream is=new FileInputStream(templatePath);
        XWPFDocument docx=new XWPFDocument(is);

        List<XWPFParagraph> paragraphs = docx.getParagraphs();
        for(XWPFParagraph p: paragraphs) {
            //遍历该格子里的段
            List<XWPFRun> runs=p.getRuns();
            for(XWPFRun run:runs) {
                //遍历该段里的所有文本
                String str=run.toString();
                //如果该段文本包含map中的key，则替换为map中的value值。
                Set<String> keySet = map.keySet();
                for(String key:keySet){
                    if(str.trim().equals("{{" + key + "}}")){
                        //替换该文本0位置的数据。
                        run.setText(map.get(key),0);
                    }
                }
            }
        }
        //输出
        OutputStream os=new FileOutputStream(outFilePath);
        docx.write(os);
        is.close();
        os.close();
        docx.close();
    }

    public static void insertStringData(XWPFDocument docx, Map<String,String> map) {

        List<XWPFParagraph> paragraphs = docx.getParagraphs();
        for(XWPFParagraph p: paragraphs) {
            //遍历该格子里的段
            List<XWPFRun> runs=p.getRuns();
            for(XWPFRun run:runs) {
                //遍历该段里的所有文本
                String str=run.toString();
                //如果该段文本包含map中的key，则替换为map中的value值。
                Set<String> keySet = map.keySet();
                for(String key:keySet){
                    if(str.trim().equals("{{" + key + "}}")){
                        //替换该文本0位置的数据。
                        run.setText(map.get(key),0);
                    }
                }
            }
        }
    }

    public static void insertImageData(XWPFDocument docx, Map<String,InputStream> map) throws Exception {

        List<XWPFParagraph> paragraphs = docx.getParagraphs();
        for(XWPFParagraph p: paragraphs) {
            //遍历该格子里的段
            List<XWPFRun> runs=p.getRuns();
            for(XWPFRun run:runs) {
                //遍历该段里的所有文本
                String str=run.toString();
                //如果该段文本包含map中的key，则替换为map中的value值。
                Set<String> keySet = map.keySet();
                if(str.trim().contains("warningRingChart")){
                    //替换该文本0位置的数据。
                    run.setText("", 0);
                    run.addPicture(map.get("warningRingBlueChart"), XWPFDocument.PICTURE_TYPE_JPEG,"", Units.toEMU(100.0), Units.toEMU(100.0));
                    //run.addPicture(map.get("warningRingYellowChart"), XWPFDocument.PICTURE_TYPE_JPEG,"", Units.toEMU(100.0),Units.toEMU(100.0));
                    //run.addPicture(map.get("warningRingOrangeChart"), XWPFDocument.PICTURE_TYPE_JPEG,"", Units.toEMU(100.0),Units.toEMU(100.0));
                    //run.addPicture(map.get("warningRingRedChart"), XWPFDocument.PICTURE_TYPE_JPEG,"", Units.toEMU(100.0),Units.toEMU(100.0));
                }
            }
        }
    }

    /**
     * 每日通报中预警数据表格
     */
    public static void insertWarningData(List<XWPFTable> tables, Map<String, List<Map<String,String>>> params){
        XWPFTable xwpfTable = tables.get(0);
        WordUtils.insertWarningsTable(xwpfTable, params);
    }

    public static void insertOtherData(List<XWPFTable> tables, List<Map<String,String>> params, int tableIndex) {
        XWPFTable xwpfTable = tables.get(tableIndex);
        WordUtils.insertValueToTable(xwpfTable, 2, params, true);
    }


    /**
     * 循环填充表格内容
     * @param params
     */
    public static void insertValueToTable(XWPFTable table, Integer startRow, List<Map<String,String>> params, Boolean deleteTemplateCol) {
        try {

            List<XWPFTableRow> rows = table.getRows();
            if (rows.size() < 2) {
                throw new Exception("tableIndex对应表格应该为2行");
            }
            // 模板的那一行
            XWPFTableRow fomatRow = rows.get(1);
            XWPFTableRow headerRow = rows.get(0);
            List<XWPFTableCell> headerCells = headerRow.getTableCells();
            List<XWPFTableCell> cells;
            XWPFTableCell headerCell;
            XWPFTableCell formatCell;

            String cellText;
            for (int i = 0, len = params.size(); i < len; i++) {
                Map<String, String> map = params.get(i);
                // 创建新的一行
                XWPFTableRow row = table.insertNewTableRow(i+startRow);
                row.getCtRow().setTrPr(fomatRow.getCtRow().getTrPr());
                // 获取模板的行高 设置为新一行的行高
                row.setHeight(fomatRow.getHeight());
                addTemplateRow(rows.get(startRow-1), row);
                cells = row.getTableCells();
                for (int k = 0, klen = cells.size(); k < klen; k++) {
                    headerCell = headerCells.get(k);
                    formatCell = fomatRow.getTableCells().get(0);
                    XWPFTableCell cell = cells.get(k);
                    cellText = headerCell.getText();
                    if (StringUtils.isNotBlank(cellText)) {
                        //转换为mapkey对应的字段
                        if (map.containsKey(cellText)) {
                            setCellText(formatCell, cell, map.get(cellText));
                        }
                    }
                }
            }
            // 删除模版行
            if(deleteTemplateCol) {
                table.removeRow(1);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     *
     * @Title: insertValueToTable
     * @Description: 向表格中写入数据
     * @param table
     * @param rowNum
     * @param params
     * @throws Exception    参数描述
     * @return void  返回类型
     * @throws
     */
    public static void insertValueToTable(XWPFTable table, Integer rowNum, Map<String,String> params) throws Exception{

        try {
            List<XWPFTableRow> rows = table.getRows();
            XWPFTableRow row = rows.get(rowNum-1);
            List<XWPFTableCell> cells = row.getTableCells();
            for (int k = 0, klen = cells.size(); k < klen; k++) {

                XWPFTableCell cell = cells.get(k);
                String cellText = cell.getText();
                if (StringUtils.isNotBlank(cellText)) {
                    //转换为mapkey对应的字段
                    if (params.containsKey(cellText)) {

                        XWPFParagraph cellP = cell.getParagraphs().get(0);
                        XWPFRun cellR = cellP.getRuns().get(0);
                        cellR.setText(params.get(cellText), 0);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 添加模板行
     * @param sourceRow
     * @param targetRow
     */
    private static void addTemplateRow(XWPFTableRow sourceRow, XWPFTableRow targetRow) {


        List<XWPFTableCell> cellList = sourceRow.getTableCells();
        if (null == cellList) {
            return;
        }

        XWPFTableCell targetCell = null;
        for (XWPFTableCell sourceCell : cellList) {
            targetCell = targetRow.addNewTableCell();
            //列属性
            targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
            //段落属性
            if(sourceCell.getParagraphs()!=null&&sourceCell.getParagraphs().size()>0){
                targetCell.getParagraphs().get(0).getCTP().setPPr(sourceCell.getParagraphs().get(0).getCTP().getPPr());
                if(sourceCell.getParagraphs().get(0).getRuns()!=null&&sourceCell.getParagraphs().get(0).getRuns().size()>0){
                    XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
                    cellR.setText(sourceCell.getText());
                    cellR.setBold(sourceCell.getParagraphs().get(0).getRuns().get(0).isBold());
                }else{
                    targetCell.setText(sourceCell.getText());
                }
            }else{
                targetCell.setText(sourceCell.getText());
            }
        }
    }

    /**
     *  复制模板行的属性并填充单元格
     * @param tmpCell
     * @param cell
     * @param text
     * @throws Exception
     */
    private static void setCellText(XWPFTableCell tmpCell, XWPFTableCell cell, String text) {

        cell.setColor(tmpCell.getColor());

        CTTc cttc2 = tmpCell.getCTTc();
        CTTcPr ctPr2 = cttc2.getTcPr();
        CTTc cttc = cell.getCTTc();
        CTTcPr ctPr = cttc.addNewTcPr();
        if (ctPr2.getTcW() != null) {
            ctPr.addNewTcW().setW(ctPr2.getTcW().getW());
        }
        if (ctPr2.getVAlign() != null) {
            ctPr.addNewVAlign().setVal(ctPr2.getVAlign().getVal());
        }

        if (ctPr2.getTcBorders() != null) {
            ctPr.setTcBorders(ctPr2.getTcBorders());
        }
        XWPFParagraph tmpParagraph = tmpCell.getParagraphs().get(0);
        XWPFParagraph cellP = cell.getParagraphs().get(0);
        // 模板行
        XWPFRun tmpRun = null;
        if (tmpParagraph.getRuns() != null && tmpParagraph.getRuns().size() > 0) {
            // 第一行为模板行
            tmpRun = tmpParagraph.getRuns().get(0);
        }

        // 写入数据
        //        XWPFRun cellR = cellP.createRun();
        //        cellR.setText(text);
        XWPFRun cellR = null;
        if(cellP.getRuns().size() == 0) {
            cellR = cellP.createRun();
        }else {
            cellR = cellP.getRuns().get(0);
        }
        cellR.setText(text, 0);


        // 复制字体信息
        if (tmpRun != null) {
            if(!cellR.isBold()){
                cellR.setBold(tmpRun.isBold());
            }
            cellR.setItalic(tmpRun.isItalic());
            cellR.setUnderline(tmpRun.getUnderline());
            cellR.setColor(tmpRun.getColor());
            cellR.setTextPosition(tmpRun.getTextPosition());
            if (tmpRun.getFontSize() != -1) {
                cellR.setFontSize(tmpRun.getFontSize());
            }
            if (tmpRun.getFontFamily() != null) {
                cellR.setFontFamily(tmpRun.getFontFamily());
            }
            if (tmpRun.getCTR() != null) {
                if (tmpRun.getCTR().isSetRPr()) {

                    CTRPr tmpRPr = tmpRun.getCTR().getRPr();

                    if (tmpRPr.isSetRFonts()) {

                        CTFonts tmpFonts = tmpRPr.getRFonts();
                        CTRPr cellRPr = cellR.getCTR().isSetRPr() ? cellR
                                .getCTR().getRPr() : cellR.getCTR().addNewRPr();
                        CTFonts cellFonts = cellRPr.isSetRFonts() ? cellRPr
                                .getRFonts() : cellRPr.addNewRFonts();
                        cellFonts.setAscii(tmpFonts.getAscii());
                        cellFonts.setAsciiTheme(tmpFonts.getAsciiTheme());
                        cellFonts.setCs(tmpFonts.getCs());
                        cellFonts.setCstheme(tmpFonts.getCstheme());
                        cellFonts.setEastAsia(tmpFonts.getEastAsia());
                        cellFonts.setEastAsiaTheme(tmpFonts.getEastAsiaTheme());
                        cellFonts.setHAnsi(tmpFonts.getHAnsi());
                        cellFonts.setHAnsiTheme(tmpFonts.getHAnsiTheme());
                    }
                }
            }
        }
        // 复制段落信息
        cellP.setAlignment(tmpParagraph.getAlignment());
        cellP.setVerticalAlignment(tmpParagraph.getVerticalAlignment());
        cellP.setBorderBetween(tmpParagraph.getBorderBetween());
        cellP.setBorderBottom(tmpParagraph.getBorderBottom());
        cellP.setBorderLeft(tmpParagraph.getBorderLeft());
        cellP.setBorderRight(tmpParagraph.getBorderRight());
        cellP.setBorderTop(tmpParagraph.getBorderTop());
        cellP.setPageBreak(tmpParagraph.isPageBreak());
        if (tmpParagraph.getCTP() != null) {
            if (tmpParagraph.getCTP().getPPr() != null) {
                CTPPr tmpPPr = tmpParagraph.getCTP().getPPr();
                CTPPr cellPPr = cellP.getCTP().getPPr() != null ? cellP
                        .getCTP().getPPr() : cellP.getCTP().addNewPPr();
                // 复制段落间距信息
                CTSpacing tmpSpacing = tmpPPr.getSpacing();
                if (tmpSpacing != null) {
                    CTSpacing cellSpacing = cellPPr.getSpacing() != null ? cellPPr
                            .getSpacing() : cellPPr.addNewSpacing();
                    if (tmpSpacing.getAfter() != null) {
                        cellSpacing.setAfter(tmpSpacing.getAfter());
                    }
                    if (tmpSpacing.getAfterAutospacing() != null) {
                        cellSpacing.setAfterAutospacing(tmpSpacing
                                .getAfterAutospacing());
                    }
                    if (tmpSpacing.getAfterLines() != null) {
                        cellSpacing.setAfterLines(tmpSpacing.getAfterLines());
                    }
                    if (tmpSpacing.getBefore() != null) {
                        cellSpacing.setBefore(tmpSpacing.getBefore());
                    }
                    if (tmpSpacing.getBeforeAutospacing() != null) {
                        cellSpacing.setBeforeAutospacing(tmpSpacing
                                .getBeforeAutospacing());
                    }
                    if (tmpSpacing.getBeforeLines() != null) {
                        cellSpacing.setBeforeLines(tmpSpacing.getBeforeLines());
                    }
                    if (tmpSpacing.getLine() != null) {
                        cellSpacing.setLine(tmpSpacing.getLine());
                    }
                    if (tmpSpacing.getLineRule() != null) {
                        cellSpacing.setLineRule(tmpSpacing.getLineRule());
                    }
                }
                // 复制段落缩进信息
                CTInd tmpInd = tmpPPr.getInd();
                if (tmpInd != null) {
                    CTInd cellInd = cellPPr.getInd() != null ? cellPPr.getInd()
                            : cellPPr.addNewInd();
                    if (tmpInd.getFirstLine() != null) {
                        cellInd.setFirstLine(tmpInd.getFirstLine());
                    }
                    if (tmpInd.getFirstLineChars() != null) {
                        cellInd.setFirstLineChars(tmpInd.getFirstLineChars());
                    }
                    if (tmpInd.getHanging() != null) {
                        cellInd.setHanging(tmpInd.getHanging());
                    }
                    if (tmpInd.getHangingChars() != null) {
                        cellInd.setHangingChars(tmpInd.getHangingChars());
                    }
                    if (tmpInd.getLeft() != null) {
                        cellInd.setLeft(tmpInd.getLeft());
                    }
                    if (tmpInd.getLeftChars() != null) {
                        cellInd.setLeftChars(tmpInd.getLeftChars());
                    }
                    if (tmpInd.getRight() != null) {
                        cellInd.setRight(tmpInd.getRight());
                    }
                    if (tmpInd.getRightChars() != null) {
                        cellInd.setRightChars(tmpInd.getRightChars());
                    }
                }
            }
        }
    }


    /**
     * 合并行
     * @param table
     * @param col
     * @param fromRow
     * @param toRow
     */
    public static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
        for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
            CTVMerge vmerge = CTVMerge.Factory.newInstance();
            if (rowIndex == fromRow) {
                vmerge.setVal(STMerge.RESTART);
            } else {
                vmerge.setVal(STMerge.CONTINUE);
            }
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
            CTTcPr tcPr = cell.getCTTc().getTcPr();
            if (tcPr != null) {
                tcPr.setVMerge(vmerge);
            } else {
                tcPr = CTTcPr.Factory.newInstance();
                tcPr.setVMerge(vmerge);
                cell.getCTTc().setTcPr(tcPr);
            }
        }
    }
    /**
     * 合并列
     *
     * @param table
     * @param row
     * @param fromCell
     * @param toCell
     */
    public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {
        for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
            if (cellIndex == fromCell) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
                //cellCount为表格总列数
                int cellCount = table.getRow(row).getTableCells().size();
                Integer width = (toCell - fromCell + 1) / cellCount * table.getCTTbl().getTblPr().getTblW().getW().intValue();
                cell.getCTTc().getTcPr().addNewTcW().setW(BigInteger.valueOf(width));
            } else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }


    /**
     *
     * @Title: insertTemplateTableCol
     * @Description: 添加表格列
     * @param table  表格
     * @param datas    待写入数据
     * @return void  返回类型
     * @throws
     */
    public static void insertTemplateTableCol(XWPFTable table, List<List<String>> datas) {

        List<XWPFTableRow> rows = table.getRows();
        for(int k = 0; k < datas.size(); k++) {

            List<String> data = datas.get(k);
            for(int i = 0; i < rows.size(); i++) {

                XWPFTableRow row = rows.get(i);
                XWPFTableCell tmpCell =  row.getCell(0);
                XWPFTableCell cell = row.createCell();
                setCellText(tmpCell, cell, data.get(i));
            }
        }
    }

    /**
     * 替换文本中的占位符
     * @param document
     * @param textMap
     */
    public static void changeText(XWPFDocument document, Map<String, Object> textMap) {
        // 获取段落集合
        // 返回包含页眉或页脚文本的段落
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        // 增强型for循环语句，前面一个为声明语句，后一个为表达式
        for (XWPFParagraph paragraph : paragraphs) {
            // 判断此段落是否需要替换
            String text = paragraph.getText();// 检索文档中的所有文本
            if (checkText(text)) {
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
                    // 替换模板原来位置
                    Object ob = changeValue(run.toString(), textMap);
                    if (ob instanceof String) {
                        if (textMap.containsKey(run.toString())) {

                            run.setText((String) ob, 0);
                        }
                    }
                }
            }
        }
    }

    /**
     *
     * @Title: insertPlaceholder
     * @Description: 插入占位符
     * @param document
     * @param sourceParagraph
     * @param key
     * @return    参数描述
     * @return XWPFParagraph  返回类型
     * @throws
     */
    private static XWPFParagraph insertPlaceholder(XWPFDocument document, XWPFParagraph sourceParagraph, String key) {

        XmlCursor cursor = sourceParagraph.getCTP().newCursor();
        cursor.toNextSibling();
        XWPFParagraph paragraphNew = document.insertNewParagraph(cursor);
        paragraphNew.getCTP().setPPr(sourceParagraph.getCTP().getPPr());
        XWPFRun xwpfRun = paragraphNew.createRun();
        xwpfRun.setText(key);
        xwpfRun.setFontSize(sourceParagraph.getRuns().get(0).getFontSize());
        xwpfRun.setFontFamily(sourceParagraph.getRuns().get(0).getFontFamily());

        return paragraphNew;
    }

    /* 检查文本中是否包含指定的字符(此处为“$”)，并返回值 */
    private static boolean checkText(String text) {
        boolean check = false;
        if (text.contains("$")) {
            check = true;
        }
        return check;
    }

    private static Object changeValue(String value, Map<String, Object> textMap) {
        Set<Map.Entry<String, Object>> textSets = textMap.entrySet();
        Object valu = "";
        for (Map.Entry<String, Object> textSet : textSets) {
            // 匹配模板与替换值 格式${key}
            String key = textSet.getKey();
            if (value.contains(key)) {
                valu = textSet.getValue();
            }
        }
        return valu;
    }

    /**
     * 循环填充表格内容
     */
    public static void insertWarningsTable(XWPFTable table, Map<String, List<Map<String,String>>> params) {
        try {
            List<Map<String, String>> redList = params.get("红色预警企业列表");
            int startRow = 1;
            if (!CollectionUtils.isEmpty(redList)){
                WordUtils.fillInWarningWordTable(table, startRow, redList, "橙色预警企业列表");
            } else {
                startRow ++; //空表格1行
            }

            List<Map<String, String>> orangeList = params.get("橙色预警企业列表");
            if (!CollectionUtils.isEmpty(orangeList)){
                WordUtils.fillInWarningWordTable(table, startRow + redList.size() + 1, orangeList, "黄色预警企业列表");
            } else {
                startRow ++; //空表格1行
            }

            List<Map<String, String>> yellowList = params.get("黄色预警企业列表");

            if (!CollectionUtils.isEmpty(yellowList)){
                WordUtils.fillInWarningWordTable(table, startRow + redList.size() + 1 + orangeList.size() + 1, yellowList, "蓝色预警企业列表");
            }

        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

    public static void fillInWarningWordTable(XWPFTable table, int startRowIndex, List<Map<String, String>> param, String nextTitle){
        List<XWPFTableRow> rows = table.getRows();
        XWPFTableRow headerRow = rows.get(1);
        List<XWPFTableCell> headerCells = headerRow.getTableCells(); //标题行的单元格list
        List<XWPFTableCell> cells;
        if (CollectionUtils.isEmpty(param)){
            return;
        }
        for (int i = 0, len = param.size(); i < len; i++) {
            //当前行数
            int currentRowNum = startRowIndex + i + 1;
            XWPFTableRow row1 = table.getRow(currentRowNum);
            XWPFTableRow row;
            if (Objects.isNull(row1)){
                //最后一行
                row = table.insertNewTableRow(currentRowNum);
                row.getCtRow().setTrPr(headerRow.getCtRow().getTrPr());
                // 获取模板的行高 设置为新一行的行高
                row.setHeight(headerRow.getHeight());
                addTemplateRow(headerRow, row);
            } else if (nextTitle.equalsIgnoreCase(row1.getCell(0).getText())){
                //新增一行
                row = table.insertNewTableRow(currentRowNum);
                row.getCtRow().setTrPr(headerRow.getCtRow().getTrPr());
                // 获取模板的行高 设置为新一行的行高
                row.setHeight(headerRow.getHeight());
                addTemplateRow(headerRow, row);
            } else {
                row = table.getRow(currentRowNum);
            }

            Map<String, String> map = param.get(i);
            cells = row.getTableCells();
            String headerTitle;
            for (int k = 0, klen = cells.size(); k < klen; k++) {
                XWPFTableCell cell = cells.get(k);//当前需要填充的单元格
                headerTitle = headerCells.get(k).getText(); //标题内容
                if (StringUtils.isNotBlank(headerTitle)) {
                    //转换为mapkey对应的字段
                    if (map.containsKey(headerTitle)) {
                        setCellText(headerCells.get(k), cell, map.get(headerTitle));
                    }
                }
            }
        }
    }
}